import Axios from 'axios'

/** 请求示例：
   request({
    url: '/xxx/xxx',
    method: 'get',
    data: { a: 1 }
  })
  request.post('/brand/create', { a: 1 })
  request.get('/brand/create', { params: { a: 1 } })
 */

const axiosConfig = {
  // `method` 是创建请求时使用的方法
  method: 'get', // default

  // `headers` 是即将被发送的自定义请求头
  // headers: { 'X-Requested-With': 'XMLHttpRequest' },

  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间，请求将被中断
  timeout: 15000

  // `withCredentials` 表示跨域请求时是否需要使用凭证
  // withCredentials: false, // default

  // `adapter` 允许自定义处理请求，以使测试更轻松
  // 返回一个 promise 并应用一个有效的响应 (查阅 [response docs](#response-api)).
  // adapter: config => {
  //   /* ... */
  // },

  // `responseType` 表示服务器响应的数据类型，可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  // responseType: 'json', // default

  // `responseEncoding` indicates encoding to use for decoding responses
  // Note: Ignored for `responseType` of 'stream' or client-side requests
  // responseEncoding: 'utf8' // default

  // `maxContentLength` 定义允许的响应内容的最大尺寸
  // maxContentLength: 2000
}

function getRequestTag (config) {
  const { url, method, data, params } = config
  return `${url}&${method}&${JSON.stringify(data || params)}`
}

// 声明一个数组用于存储每个ajax请求的取消函数和ajax标识
const cancelTokens = []
function cancelRequest (config) {
  cancelTokens.forEach((cancelToken, i) => {
    const { tag, cancel } = cancelToken
    // 当当前请求在数组中存在时执行函数体
    if (tag === getRequestTag(config)) {
      // 执行取消操作
      cancel()

      // 把这条记录从数组中移除
      cancelTokens.splice(i, 1)
    }
  })
}

export function createAxios (options) {
  const axios = Axios.create({
    ...axiosConfig,
    ...options
  })

  let counter = 0
  // 添加请求拦截器，在发送请求之前做些什么
  axios.interceptors.request.use(
    config => {
      // console.log('请求拦截器', config)
      counter += 1
      //
      const { method } = config
      let newConfig = config
      if (method && method.toUpperCase() === 'GET') {
        const { data, params, ...rest } = config
        newConfig = {
          ...rest,
          params: data || params
        }
        // console.log('newConfig', newConfig)
      }
      // 在一个ajax发送前执行一下是否取消请求操作（如果同样的一个请求还在请求中则取消上一个请求）
      cancelRequest(config)
      //
      newConfig = {
        ...newConfig,
        cancelToken: new Axios.CancelToken(cancel => {
          // 这里的ajax标识用请求地址&请求方式拼接的字符串
          cancelTokens.push({ tag: getRequestTag(config), cancel })
        })
      }
      // 携带自定义token
      config.headers['Authorization'] = 'token'
      return newConfig
    },
    error => {
      counter -= 1
      if (counter === 0) {
        // store.dispatch(toggleLoading) // 隐藏菊花
      }
      // 对请求错误做些什么
      return Promise.reject(error)
    }
  )

  // 添加响应拦截器，对响应数据做点什么
  axios.interceptors.response.use(
    response => {
      // console.log('响应拦截器', response)
      counter -= 1
      if (counter === 0) {
        // store.dispatch(toggleLoading) // 隐藏菊花
      }
      // 在一个ajax响应后再执行一下取消操作，把已经完成的请求从pending中移除
      cancelRequest(response.config)
      // const { data, config, headers, status, statusText } = response
      return response
    },
    error => {
      // console.error('error', error)
      // 对响应错误做点什么1
      // return Promise.reject(error)
      counter -= 1
      if (counter === 0) {
        // store.dispatch(toggleLoading) // 隐藏菊花
      }
      // return { data: {}, error }
      return Promise.reject(error)
    }
  )
  return axios
}

// 创建axios实例
const service = createAxios({
  baseURL: process.env.BASE_API // api的base_url 在config文件夹中配置
})

export default service
